<?php


namespace App\Logic;


use App\Base\AuthManager;
use App\Base\ErrCode;
use App\Support\Database\DbManager;
use App\Support\Redis\MyRedis;
use App\Support\Redis\RedisManager;
use App\Support\Time\Time;
use \Exception;

class BlessLogic
{
    /**
     * 留言-插入数据库
     * @param $param
     * @return array
     */
    public function leaveMessage($param): array
    {
        arrayAddslashes($param);
        $db = DbManager::getInstance();
        $user = AuthManager::getPayload();


        //由于每个用户只能留言一次，这里用mysql主键唯一性来做并发限制
        try {
            $db->beginTransaction();

            $exists = $db->first('SELECT userid FROM msg WHERE userid = ' . $user['userid']);
            if ($exists) {
                return [ErrCode::$failCode, [], '每人留言不能超过一条'];
            }

            $db->insert(
                'msg',
                [
                    'userid' => $user['userid'],
                    'text' => $param['bless'],
                    'created_at' => Time::now()->toDateTime()
                ]
            );
            $db->commit();
            return [ErrCode::$successCode, [], '留言成功'];
        } catch (\Throwable $e) {
            $db->rollback();
            return [ErrCode::$failCode, [], '留言失败，请稍候再试'];
        }
    }

    /**
     * 留言-列表
     * @param $param
     * @return array
     */
    public function msgList($param): array
    {
        $db = DbManager::getInstance();

        $pageNo = isset($param['pageNo']) ? intval($param['pageNo']) : 1;
        $pageSize = isset($param['pageSize']) ? intval($param['pageSize']) : 20;

        $totalCount = $db->getCount('msg', 'userid');

        $offset = ($pageNo - 1) * $pageSize;

        $msgList = $db->all(
            "SELECT U.userid, U.username, `text`, M.`created_at` FROM `msg` as M 
LEFT JOIN `user` as U ON M.userid = U.userid ORDER BY M.`created_at` DESC LIMIT {$offset} , {$pageSize}"
        );

        return [
            'pageNo' => $pageNo,
            'pageSize' => $pageSize,
            'totalCount' => $totalCount,
            'totalPage' => ceil($totalCount / $pageSize),
            'list' => $msgList
        ];
    }

    /**
     * 留言-榜单
     * @return array
     */
    public function msgRankList(): array
    {
        $db = DbManager::getInstance();

        $rank = $db->all('SELECT count(1) as `like_count`, `msgid` FROM `like_msg` GROUP BY `msgid` LIMIT 100');
        $rankFmt = array_column($rank, 'like_count', 'msgid');
        if ($rank) {
            $msgList = $db->all(
                "SELECT U.userid, U.username, `text`, M.`created_at` FROM `msg` as M 
LEFT JOIN `user` as U ON M.userid = U.userid WHERE M.userid IN(" . join(',', array_keys($rankFmt)) . ")"
            );
        } else {
            $msgList = [];
        }
        foreach ($msgList as &$item) {
            $item['like_count'] = $rankFmt[$item['userid']];
        }
        return $msgList;
    }


    /**
     * 点赞
     * @param $param
     * @return array
     * @throws \Throwable
     */
    public function likeBless($param)
    {
        arrayAddslashes($param);
        $user = AuthManager::getPayload();
        $db = DbManager::getInstance();
        $redis = RedisManager::getInstance();
        $date = date('Ymd');
        $likeRedisKey = 'likeCount:' . $date . ':' . $user['userid'];//每个用户每天的点赞限制
        $likeRedisKeyExpireAt = strtotime($date) + 86400;

        $likeLogicBeing = 'likeLogicBeing:' . $user['userid'] . '-' . $param['msgid'];//用于上锁，incr操作返回1 表示接受本次请求，大于1 表示拒绝本次请求

        //限制一个人单日点赞数是单用户并发，这里用redis锁
        try {
            if ($redis->incr($likeLogicBeing) > 1) {
                throw new Exception('操作太频繁，休息一下吧');
            }

            //判断重复一定要在判断今日第那咱数量之前，不然点赞不成功，点赞数却已自增，自增到10就没法再点赞了
            $existsCount = $db->getCount('like_msg','1',"userid = {$user['userid']} AND msgid = {$param['msgid']}");
            if ($existsCount) {
                throw new Exception('重复点赞');
            }

            if ($redis->incr($likeRedisKey) > BusinessLogic::$activity['like_per_day']) {
                throw new Exception('今日点赞数量已达' . BusinessLogic::$activity['like_per_day'] . '次');
            }

            $db->insert(
                'like_msg',
                [
                    'userid' => $user['userid'],
                    'msgid' => $param['msgid'],
                    'created_at' => Time::now()->toDateTime()
                ]
            );

            $redis->expireAt($likeRedisKey, $likeRedisKeyExpireAt);
            $redis->expire($likeLogicBeing, 1);

            return [ErrCode::$successCode, [], '点赞成功'];
        } catch (\Throwable $e) {
            $redis->expireAt($likeRedisKey, $likeRedisKeyExpireAt);
            $redis->expire($likeLogicBeing, 1);
            return [ErrCode::$failCode, [], $e->getMessage()];
        }
    }
}